package assignment;

import java.io.IOException;
import java.net.MalformedURLException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import assignment.jaxb.Card;
import assignment.jaxb.Cards;

/**
 * @author $Author:$
 * @version $Id: $
 */
public class GPUReviewParser {

	public String baseURL;
	
	/**
	 * @param baseURL base URL of the web page to parse
	 */
	public GPUReviewParser(String baseURL) {
		super();
		this.baseURL = baseURL;
	}

	/**
	 * @param stringBuffer the web page data
	 * @return List of graphic cards parsed
	 * @throws IOException 
	 * @throws MalformedURLException 
	 */
	public Cards parseMasterPage(StringBuffer stringBuffer) throws MalformedURLException, IOException {

		// Expression for graphic card detail suffix and graphic card name identification
		String regEx = ".html\"><img src=\"([^\"]*)\".*?<a href=\"([^\"]*)\"\\s+class=\"search-result\"[^>]*>([^<]+)</a>";
				
		// Pattern compiled with expression from previous step
		Pattern p = Pattern.compile(regEx, Pattern.DOTALL | Pattern.UNIX_LINES);
		
		// Generate all matching occurrences of the previous expression
		Matcher m = p.matcher(stringBuffer);
		
		Cards cardList = new Cards(); 
		
		// Generate cards data
		while(m.find()){
			
			String imageFileUrlSuffix = m.group(1);
			String urlSuffix = m.group(2);
			String cardName = m.group(3);
			
			Card graphicCard = new Card();
			
			imageFileUrlSuffix = imageFileUrlSuffix.replaceAll("/small/", "/large/");
			imageFileUrlSuffix = imageFileUrlSuffix.replaceAll("not-available-sm.", "not-available.");
			
			graphicCard.setGraphicCardName(cardName);
			graphicCard.setUrl(this.baseURL + urlSuffix); 
			graphicCard.setImageFileUrl(this.baseURL + imageFileUrlSuffix);
			
			cardList.add(graphicCard);	
		}
		
		return cardList;
	}

	/**
	 * @param stringBuffer the web page data
	 * @param graphicCard the graphic card data
	 */
	public void parseDetailPage(StringBuffer stringBuffer, Card graphicCard) {
		// Expression for graphic card detail suffix and graphic card name identification
		String[] regExSet = new String[36];
		
		regExSet[0] = "manufacturer-article[^>]*>[^>]*>[^>]*>[^>]*>([^<]*)</td></tr>";
		
		regExSet[1] = "series-article[^>]*>[^>]*>[^>]*>[^>]*>([^<]*)</td></tr>";
				
		regExSet[2] = "gpu-article[^>]*>[^>]*>[^>]*>[^>]*><[^>]*>([^<]*)</a>([^<]*)</td></tr>";
		
		regExSet[3] = "release-date-article[^>]*>[^>]*>[^>]*>[^>]*>([^<]*)</td></tr>";
		
		regExSet[4] = "interface-article[^>]*>[^>]*>[^>]*>[^>]*>([^<]*)</td></tr>";
		
		regExSet[5] = "core-clock-article[^>]*>[^>]*>[^>]*>[^>]*><[^>]*>([^<]*)</span>([^<]*)</td></tr>";
		
		regExSet[6] = "memory-clock-article[^>]*>[^>]*>[^>]*>[^>]*><[^>]*>([^<]*)</span>([^<]*)<?[^>]*>?([^<]*?)<?/?s?p?a?n?>?([^<]*?)</td></tr>";
		
		regExSet[7] = "memory-bandwidth-article[^>]*>[^>]*>[^>]*>[^>]*><[^>]*>([^<]*)</span>([^<]*)</td></tr>";
		
		regExSet[8] = "shader-operations-article[^>]*>[^>]*>[^>]*>[^>]*><[^>]*>([^<]*)</span>([^<]*)</td></tr>";
		
		regExSet[9] = "pixel-fill-rate-article[^>]*>[^>]*>[^>]*>[^>]*><[^>]*>([^<]*)</span>([^<]*)</td></tr>";
		
		regExSet[10] = "texture-fill-rate-article[^>]*>[^>]*>[^>]*>[^>]*><[^>]*>([^<]*)</span>([^<]*)</td></tr>";
		
		regExSet[11] = "vertex-operations-article[^>]*>[^>]*>[^>]*>[^>]*><[^>]*>([^<]*)</span>([^<]*)</td></tr>";
		
		regExSet[12] = "noise-level-article[^>]*>[^>]*>[^>]*>[^>]*>(.*?)</td></tr>";
		
		regExSet[13] = "framebuffer-article[^>]*>[^>]*>[^>]*>[^>]*>(.*?)</td></tr>";
		
		regExSet[14] = "memory-type-article[^>]*>[^>]*>[^>]*>[^>]*>([^<]*)</td></tr>";
		
		regExSet[15] = "memory-bus-type-article[^>]*>[^>]*>[^>]*>[^>]*>([^<]*)</td></tr>";
		
		regExSet[16] = "directx-compliance-article[^>]*>[^>]*>[^>]*>[^>]*>([^<]*)</td></tr>";
		
		regExSet[17] = "opengl-compliance-article[^>]*>[^>]*>[^>]*>[^>]*>([^<]*)</td></tr>";
		
		regExSet[18] = "pixel-shader-version-article[^>]*>[^>]*>[^>]*>[^>]*>([^<]*)</td></tr>";
		
		regExSet[19] = "manufacturing-process-article[^>]*>[^>]*>[^>]*>[^>]*>([^<]*)</td></tr>";
		
		regExSet[20] = "fragment-pipeline-article[^>]*>[^>]*>[^>]*>[^>]*><[^>]*>([^<]*)</span>([^<]*)<?[^>]*>?([^<]*?)<?/?s?p?a?n?>?([^<]*?)</td></tr>";
					
		regExSet[21] = "vertex-pipeline-article[^>]*>[^>]*>[^>]*>[^>]*><[^>]*>([^<]*)</span>([^<]*)</td></tr>";
		
		regExSet[22] = "texture-units-article[^>]*>[^>]*>[^>]*>[^>]*><[^>]*>([^<]*)</span>([^<]*)<?[^>]*>?([^<]*?)<?/?s?p?a?n?>?([^<]*?)</td></tr>";
		
		regExSet[23] = "raster-operator-article[^>]*>[^>]*>[^>]*>[^>]*><[^>]*>([^<]*)</span>([^<]*)<?[^>]*>?([^<]*?)<?/?s?p?a?n?>?([^<]*?)</td></tr>";
		
		regExSet[24] = "gpu-rating-label\">Overall</div>.*?gpu-rating-score\"><strong>([^<]*)</strong>";
		
		regExSet[25] = "gpu-rating-label\">Overall</div>.*?gpu-rating-score\"><strong>[^<]*</strong>[^0-9]*([^\\s]*)\\svotes";
		
		regExSet[26] = "gpu-rating-label\">Performance</div>.*?gpu-rating-score\"><strong>([^<]*)</strong>";
		
		regExSet[27] = "gpu-rating-label\">Performance</div>.*?gpu-rating-score\"><strong>[^<]*</strong>[^0-9]*([^\\s]*)\\svotes";
		
		regExSet[28] = "gpu-rating-label\">Price</div>.*?gpu-rating-score\"><strong>([^<]*)</strong>";
		
		regExSet[29] = "gpu-rating-label\">Price</div>.*?gpu-rating-score\"><strong>[^<]*</strong>[^0-9]*([^\\s]*)\\svotes";
		
		regExSet[30] = "gpu-rating-label\">Features</div>.*?gpu-rating-score\"><strong>([^<]*)</strong>";
		
		regExSet[31] = "gpu-rating-label\">Features</div>.*?gpu-rating-score\"><strong>[^<]*</strong>[^0-9]*([^\\s]*)\\svotes";
		
		regExSet[32] = "gpu-rating-label\">Overclockability</div>.*?gpu-rating-score\"><strong>([^<]*)</strong>";
		
		regExSet[33] = "gpu-rating-label\">Overclockability</div>.*?gpu-rating-score\"><strong>[^<]*</strong>[^0-9]*([^\\s]*)\\svotes";
		
		regExSet[34] = "gpu-rating-label\">Silence</div>.*?gpu-rating-score\"><strong>([^<]*)</strong>";
		
		regExSet[35] = "gpu-rating-label\">Silence</div>.*?gpu-rating-score\"><strong>[^<]*</strong>[^0-9]*([^\\s]*)\\svotes";
		
		
		int regExIndex = 0;
		
		for(String regEx: regExSet ){
			// Pattern compiled with expression from previous step
			Pattern p = Pattern.compile(regEx, Pattern.DOTALL | Pattern.UNIX_LINES);
			
			// Generate all matching occurrences of the previous expression
			Matcher m = p.matcher(stringBuffer);
						
			while(m.find()){
				
				// Define the extracted value
				String extractedValue = "";
				
				for( int groupIndex = 1; groupIndex <= m.groupCount(); groupIndex++){
					extractedValue += m.group(groupIndex);
				}
				
				switch(regExIndex){
					case 0:
						graphicCard.setManufacturer(extractedValue);
						break;
					case 1:
						graphicCard.setSeries(extractedValue);
						break;
					case 2:
						graphicCard.setGPU(extractedValue);
						break;
					case 3:
						graphicCard.setReleaseDate(extractedValue);
						break;
					case 4:
						graphicCard.setInterface(extractedValue);
						break;
					case 5:
						graphicCard.setCoreClock(extractedValue);
						break;
					case 6:
						graphicCard.setMemoryClock(extractedValue);
						break;
					case 7:
						graphicCard.setMemoryBandwidth(extractedValue);
						break;
					case 8:
						graphicCard.setShaderOperations(extractedValue);
						break;
					case 9:
						graphicCard.setPixelFillRate(extractedValue);
						break;
					case 10:
						graphicCard.setTextureFillRate(extractedValue);
						break;
					case 11:
						graphicCard.setVertexOperations(extractedValue);
						break;
						
					// Card details
					case 12:
						graphicCard.getDetails().setNoiseLevel(extractedValue);
						break;
					case 13:
						graphicCard.getDetails().setFramebuffer(extractedValue);
						break;
					case 14:
						graphicCard.getDetails().setMemoryType(extractedValue);
						break;
					case 15:
						graphicCard.getDetails().setMemoryBusType(extractedValue);
						break;
					case 16:
						graphicCard.getDetails().setDirectXCompliance(extractedValue);
						break;
					case 17:
						graphicCard.getDetails().setOpenGLCompliance(extractedValue);
						break;
					case 18:
						graphicCard.getDetails().setPsvsVersion(extractedValue);
						break;
					case 19:
						graphicCard.getDetails().setProcess(extractedValue);
						break;
					case 20:
						graphicCard.getDetails().setFragmentPipelines(extractedValue);
						break;
					case 21:
						graphicCard.getDetails().setVertexPipelines(extractedValue);
						break;
					case 22:
						graphicCard.getDetails().setTextureUnits(extractedValue);
						break;
					case 23:
						graphicCard.getDetails().setRasterOperators(extractedValue);
						break;
					case 24:
						graphicCard.getDetails().setGpuRatingOverall(Double.valueOf(extractedValue));
						break;
					case 25:
						graphicCard.getDetails().setGpuRatingOverallVotes(Integer.valueOf(extractedValue));
						break;
					case 26:
						graphicCard.getDetails().setGpuRatingPerformance(Double.valueOf(extractedValue));
						break;
					case 27:
						graphicCard.getDetails().setGpuRatingPerformanceVotes(Integer.valueOf(extractedValue));
						break;
					case 28:
						graphicCard.getDetails().setGpuRatingPrice(Double.valueOf(extractedValue));
						break;
					case 29:
						graphicCard.getDetails().setGpuRatingPriceVotes(Integer.valueOf(extractedValue));
						break;
					case 30:
						graphicCard.getDetails().setGpuRatingFeatures(Double.valueOf(extractedValue));
						break;
					case 31:
						graphicCard.getDetails().setGpuRatingFeaturesVotes(Integer.valueOf(extractedValue));
						break;
					case 32:
						graphicCard.getDetails().setGpuRatingOverclockability(Double.valueOf(extractedValue));
						break;
					case 33:
						graphicCard.getDetails().setGpuRatingOverclockabilityVotes(Integer.valueOf(extractedValue));
						break;
					case 34:
						graphicCard.getDetails().setGpuRatingSilence(Double.valueOf(extractedValue));
						break;
					case 35:
						graphicCard.getDetails().setGpuRatingSilenceVotes(Integer.valueOf(extractedValue));
						break;
					default:
						System.out.print("Invalid regular expression index");
				}
				
			}
			
			regExIndex++;
		}
		
		System.out.println(graphicCard.toString());
	}

}
